/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sirtet.netplay;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import sirtet.Player;
import sirtet.event.PlayerActionEvent;
import sirtet.event.PlayerEvent;
import sirtet.event.PlayerListener;

/**
 * This class wraps a player object, so that all invoked actions, as well as
 * player state changes, are relayed to the remote peer (server).
 * @author marucs
 */
public class PlayerPipe implements PlayerListener {

    private Player player;
    private Communicator communicator;
    private static Set<PlayerPipe> proxies = new HashSet<PlayerPipe>();

    protected PlayerPipe(Player player, Communicator comm) {
        if (player == null || comm == null) {
            throw new NullPointerException();
        }

        this.player = player;
        this.communicator = comm;

        player.addPlayerListener(this);
    }

    @Override
    public void actionPerformed(PlayerActionEvent evt) {
        try {
            this.communicator.send(evt.action.toString());
        } catch (IOException ex) {
            // The communicator is not reliable
            disconnectAll(this.communicator);
        }
    }

    @Override
    public void playerQuit(PlayerEvent evt) {
        this.communicator.post(ServerResponse.QUIT);
    }

    @Override
    public void playerEnabled(PlayerEvent evt) {
        this.communicator.post(ServerResponse.START);
    }

    @Override
    public void playerDisabled(PlayerEvent evt) {
        this.communicator.post(ServerResponse.STOP);
    }

    @Override
    public void playerReady(PlayerEvent evt){
        this.communicator.post(ClientResponse.READY);
    }

    public static void connect(Player player, Communicator comm) {
        PlayerPipe proxy = new PlayerPipe(player, comm);

        proxies.add(proxy);
    }

    public static void disconnect(Player player, Communicator comm) {
        for (PlayerPipe proxy : proxies) {
            if (proxy.player == player && proxy.communicator == comm) {
                player.removePlayerListener(proxy);
                proxies.remove(proxy);
                break;
            }
        }
    }

    public static void disconnectAll(Player player) {
        boolean finished = false;

        while (!finished) {
            finished = true;
            for (PlayerPipe proxy : proxies) {
                if (proxy.player == player) {
                    player.removePlayerListener(proxy);
                    proxies.remove(proxy);
                    finished = false;
                    break;
                }
            }
        }
    }

    public static void disconnectAll(Communicator comm) {
        boolean finished = false;

        while (!finished) {
            finished = true;
            for (PlayerPipe proxy : proxies) {
                if (proxy.communicator == comm) {
                    proxy.player.removePlayerListener(proxy);
                    proxies.remove(proxy);
                    finished = false;
                    break;
                }
            }
        }
    }
}
